package com.valley.boot;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.LoaderClassPath;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public abstract class AbstractTransform implements ClassFileTransformer {


    protected abstract void transformClass(ClassPool classPool,CtClass ctClass) throws Exception;

    protected abstract String getClassName();

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

        String classNameNew = className.replace("/", ".");

        if (classNameNew.equals(getClassName())){
            try {
                System.out.println("当前ClassLoader " + ( loader == null? null : loader.getClass().getName() )
                                + " 当前类： " + className +
                "  classBeingRedefined :" + (classBeingRedefined == null ? null : classBeingRedefined.getName()) + " main:"
                + (protectionDomain == null ? null :protectionDomain.getClass().getName()));
                ClassPool classPool = ClassPool.getDefault();
                ClassLoader classLoader = ClassLoaderUtil.getClassLoader(loader);
                classPool.insertClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
                classPool.appendClassPath(new LoaderClassPath(classLoader));
                classPool.appendClassPath(new ClassClassPath(classBeingRedefined));
                CtClass ctClass = classPool.getCtClass(getClassName());
                if (ctClass == null){
                    System.out.println("未找到类["+getClassName()+"] 当前classloader是["+( loader == null? null : loader.getClass().getName() )+"]");
                    return null;
                }

                transformClass(classPool,ctClass);

                byte[] bytes = ctClass.toBytecode();
                ctClass.detach();
                return bytes;
            } catch (Exception e) {
                System.out.println("类["+getClassName()+"]解析出错:" + e.getMessage() + "  " + e.getLocalizedMessage());
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
        return classfileBuffer;
    }
}
